package com.blog.interceptor;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.blog.Utils.CookieUtils;
import com.blog.Utils.RedirectUtils;
import com.blog.annotion.LoginAnnotatio;
import com.blog.base.Constans;
import com.blog.base.ThreadLocalToken;
import com.blog.base.ThreadLocalUserId;
import com.blog.bean.domain.User;
import com.blog.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * 配置用户状态拦截器。
 * @author 任浩
 * @version 1.0
 */

@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Resource
    private UserMapper userMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("进入了拦截器的方法*********************************");
        log.info("拦截到的请求为：" + request.getRequestURI());
        //如果当前拦截的是方法，进行判断是否拦截
        if(handler instanceof HandlerMethod){
            //把当前的handler转化为handlerMethod
            HandlerMethod handler1 = (HandlerMethod) handler;
            //得到方法
            Method method = handler1.getMethod();
            /**
             * 如果当前请求的方法上使用了LoginAnnotatio注解，并且session中没有值，就拦截。（这种方式在于我们需要手动在方法上添加LoginAnnotatio注解）
             * 注意： LoginAnnotatio是自定义的注解 todo
             */
            LoginAnnotatio annotation = method.getAnnotation(LoginAnnotatio.class);
            if(annotation == null){
                log.info("拦截器直接放行");
                return true;
            }
//            HttpSession session = request.getSession(); //得到sessiond对象，获取是否有用户值。
//            if(annotation != null && session.getAttribute("userId") == null ){
//                log.info("拦截成功");
//                byte i = 0;
//                /**
//                 * 应该重定向到登录页面。
//                 */
//                response.getWriter().write("-1");
//                return false;
//            }

            /**
             * 在这里对用户进行两次检查，
             * 一次是对获取到的token进行检查，另一次是对获取到的userId进行检查。
             */
            Map<String,String> data = CookieUtils.getCookieMessage(request);
            log.info("获取到的cookie的值为：" + data);
            String accessToken = data.get(Constans.Cookie_Token);
            String userId = data.get(Constans.Cookie_User);

            if(accessToken == null || userId == null) {
                //清除response设置的Cookie值
                CookieUtils.removeCookie(response);
                RedirectUtils.setRedirect(response);
                return false;
            }
            /**
             * 如果token存在，那么判断用户信息是否一致.
             * 需要用token拿到用户信息的id值，与当前cookie带过来的id值做比较。这里根据token到redis拿取用户信息。
             */
            log.info("通过cookie拿到的token为：" + accessToken);
            log.info("通过cookie拿到的id为：" + userId);

            String token = stringRedisTemplate.opsForValue().get(userId);
            log.info("查询出来的token为：" + token);
            if(token == null || !token.equals(accessToken)){
                CookieUtils.removeCookie(response);
                RedirectUtils.setRedirect(response);
                return false;
            }
            /**
             * 根据userid，到数据库查询用户是否存在
             */
            QueryWrapper<User> queryWrapper = new QueryWrapper<User>().eq("id",Integer.parseInt(userId));
            List<User> select = userMapper.selectList(queryWrapper);
            log.info("查询出来的用户信息为：" + select);
            if(select.size()!=1){
                CookieUtils.removeCookie(response);

                RedirectUtils.setRedirect(response);
                return false;
            }
            log.info("鉴权通过");
            /**
             * 在ThreadLocal中设置token和userId
             */
            ThreadLocalToken.set(accessToken);
            ThreadLocalUserId.set(userId);
        }

        return true;
    }

//    @Override
//    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//    }
//
//    @Override
//    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//
//    }
}
